#include "storage_device_impl.h"
#include <sys/statvfs.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <unistd.h>
#include <cstring>
#include <system_error>
#include "utils_log.h"
#include "utils_system.h"
#include "utils_file_ex.h"
#include <map>

namespace El {
namespace Storage {

namespace {
struct FileSystemMapping {
    const char *fsName;
    FileSystemType fsType;
};

constexpr FileSystemMapping FS_MAPPINGS[] = {
    {"vfat", FileSystemType::FAT32},
    {"exfat", FileSystemType::EXFAT},
    {"ntfs", FileSystemType::NTFS},
};

// 文件系统类型转换为字符串
const char *FileSystemTypeToString(FileSystemType type)
{
    for (const auto &mapping : FS_MAPPINGS) {
        if (mapping.fsType == type) {
            return mapping.fsName;
        }
    }
    return "vfat"; // 默认使用FAT32
}

// 字符串转换为文件系统类型
FileSystemType StringToFileSystemType(const std::string &fsName)
{
    for (const auto &mapping : FS_MAPPINGS) {
        if (fsName == mapping.fsName) {
            return mapping.fsType;
        }
    }
    return FileSystemType::ERR_UNKNOWN;
}
} // namespace

StorageDeviceImpl::StorageDeviceImpl(DeviceType type, std::string devicePath, std::string mountPath)
    : type_(type), devicePath_(std::move(devicePath)), mountPoint_(std::move(mountPath))
{
    fileSystemType_ = DetectFileSystemType();
}

DeviceType StorageDeviceImpl::GetType() const
{
    return type_;
}

std::string StorageDeviceImpl::GetDevicePath() const
{
    return devicePath_;
}

std::string StorageDeviceImpl::GetMountPoint() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return mountPoint_;
}

DeviceStatus StorageDeviceImpl::GetStatus() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    return status_;
}

bool StorageDeviceImpl::Mount()
{
    if (isMounted_) {
        return true;
    }

    // 检查设备是否已经被挂载到其他位置
    std::string output;
    std::string command = "cat /proc/mounts | grep " + actualDevicePath_;
    if (Utils::ExecuteCommand(command, &output)) {
        if (!output.empty()) {
            EL_INFO("Device {} is already mounted somewhere", actualDevicePath_);
            isMounted_ = true;
            status_ = DeviceStatus::ERR_MOUNTED;
            return true;
        }
    }

    if (!Utils::CreateDirectories(mountPoint_)) {
        EL_ERROR("CreateDirectories failed: {}", mountPoint_.c_str());
        return false;
    }

    bool mountSuccess = false;
    const char *fstype = FileSystemTypeToString(fileSystemType_);

    // NTFS文件系统使用ntfs-3g挂载
    if (fileSystemType_ == FileSystemType::NTFS) {
        std::string ntfs_command = "ntfs-3g " + actualDevicePath_ + " " + mountPoint_;
        mountSuccess = Utils::ExecuteCommand(ntfs_command, &output);
        if (!mountSuccess) {
            EL_ERROR("ntfs-3g mount failed: {} {}", ntfs_command, output);
            status_ = DeviceStatus::ERR_ERROR;
            return false;
        }
    } else {
        // 使用内核驱动挂载其他文件系统
        std::string mount_options = "errors=continue";
        mountSuccess = (mount(actualDevicePath_.c_str(), mountPoint_.c_str(), fstype,
                              MS_NOATIME | MS_NOSUID | MS_NODEV | MS_NOEXEC, mount_options.c_str()) == 0);
        if (!mountSuccess) {
            EL_ERROR("mount failed: {} {} {} {} {}", actualDevicePath_.c_str(), mountPoint_.c_str(), fstype,
                      mount_options.c_str(), strerror(errno));
            status_ = DeviceStatus::ERR_ERROR;
            return false;
        }
    }

    isMounted_ = true;
    status_ = DeviceStatus::ERR_MOUNTED;

    // 检查并修复文件系统（如果需要）
    if (!CheckAndRepairIfNeeded()) {
        EL_ERROR("Failed to check and repair filesystem");
        Unmount();
        return false;
    }

    // 创建挂载状态文件
    if (!CreateMountStatusFile()) {
        EL_ERROR("Failed to create mount status file");
        Unmount();
        return false;
    }

    return true;
}

bool StorageDeviceImpl::Unmount()
{
    if (!isMounted_) {
        return true;
    }

    // 先删除挂载状态文件
    RemoveMountStatusFile();

    EL_INFO("Unmounting device: {} start", mountPoint_.c_str());
    if (umount2(mountPoint_.c_str(), MNT_FORCE) != 0) {
        if (errno == EBUSY) {
            EL_INFO("Device is busy, syncing data");

            sync();
            // 再次尝试强制卸载
            if (umount2(mountPoint_.c_str(), MNT_FORCE | MNT_DETACH) != 0) {
                EL_ERROR("umount2 failed: {} {}", mountPoint_.c_str(), strerror(errno));
                return false;
            }
        } else {
            EL_ERROR("umount2 failed: {} {}", mountPoint_.c_str(), strerror(errno));
            return false;
        }
    }
    EL_INFO("Unmounting device: {} end", mountPoint_.c_str());

    isMounted_ = false;
    status_ = DeviceStatus::ERR_UNMOUNTED;
    return true;
}

bool StorageDeviceImpl::Format(FileSystemType fsType)
{
    // TODO: 实现格式化功能
    (void)fsType; // 避免未使用参数警告
    return false;
}

StorageCapacity StorageDeviceImpl::GetCapacity() const
{
    std::lock_guard<std::mutex> lock(mutex_);
    if (!isMounted_) {
        return StorageCapacity{};
    }

    struct statvfs stat;
    StorageCapacity capacity{};

    if (statvfs(mountPoint_.c_str(), &stat) == 0) {
        // 使用 uint64_t 确保计算不会溢出
        uint64_t blockSize = static_cast<uint64_t>(stat.f_frsize);
        uint64_t totalBlocks = static_cast<uint64_t>(stat.f_blocks);
        uint64_t availableBlocks = static_cast<uint64_t>(stat.f_bavail);

        // 检查乘法溢出
        if (totalBlocks > std::numeric_limits<uint64_t>::max() / blockSize) {
            EL_ERROR("Total size calculation would overflow for device: {}", mountPoint_);
            return StorageCapacity{};
        }

        capacity.totalBytes = totalBlocks * blockSize;
        capacity.availableBytes = availableBlocks * blockSize;

        // 检查减法是否会导致负数
        if (capacity.availableBytes > capacity.totalBytes) {
            EL_ERROR("Available size larger than total size for device: {}", mountPoint_);
            return StorageCapacity{};
        }

        capacity.usedBytes = capacity.totalBytes - capacity.availableBytes;

        // 避免除零错误，同时确保百分比计算正确
        if (capacity.totalBytes > 0) {
            capacity.usagePercentage =
                static_cast<int32_t>((static_cast<double>(capacity.usedBytes) * 100.0) / capacity.totalBytes);
        } else {
            capacity.usagePercentage = 0;
        }
    }
    EL_TRACE("Device {} capacity: totalBytes {} usedBytes {} availableBytes {} usagePercentage {}", mountPoint_,
              capacity.totalBytes, capacity.usedBytes, capacity.availableBytes, capacity.usagePercentage);

    return capacity;
}

FileSystemType StorageDeviceImpl::DetectFileSystemType()
{
    // 检查设备路径是否存在
    if (!Utils::IsFileExists(devicePath_)) {
        EL_ERROR("Device path does not exist: {}", devicePath_);
        return FileSystemType::ERR_UNKNOWN;
    }
    actualDevicePath_ = devicePath_;

    // 检查是否是块设备且没有分区号
    if (devicePath_.find_last_of("0123456789") == std::string::npos) {
        // 遍历查找设备的第一个可用分区
        for (int i = 1; i <= 9; i++) {
            std::string partition = devicePath_ + std::to_string(i);
            if (Utils::IsFileExists(partition)) {
                // 验证是否为块设备
                struct stat st;
                if (stat(partition.c_str(), &st) == 0 && S_ISBLK(st.st_mode)) {
                    EL_INFO("Found first available partition: {}", partition);
                    actualDevicePath_ = partition;
                    break;
                }
            }
        }
        if (actualDevicePath_ == devicePath_) {
            EL_WARN("No valid partition found on device: {}", devicePath_);
        }
    }

    // 首先尝试使用 blkid 命令
    std::string output;
    std::string command = "blkid " + actualDevicePath_;
    if (Utils::ExecuteCommand(command, &output)) {
        // 解析 blkid 输出中的 TYPE 字段
        size_t typePos = output.find("TYPE=\"");
        if (typePos != std::string::npos) {
            typePos += 6; // 跳过 "TYPE=\""
            size_t endPos = output.find('\"', typePos);
            if (endPos != std::string::npos) {
                std::string fsType = output.substr(typePos, endPos - typePos);
                EL_INFO("Detected filesystem type by blkid: {} for device: {}", fsType, actualDevicePath_);

                FileSystemType type = StringToFileSystemType(fsType);
                if (type != FileSystemType::ERR_UNKNOWN) {
                    return type;
                }
            }
        }
    }

    // 如果 blkid 失败，直接读取分区头部信息
    int fd = open(actualDevicePath_.c_str(), O_RDONLY);
    if (fd < 0) {
        EL_ERROR("Failed to open device for filesystem detection: {} {}", actualDevicePath_, strerror(errno));
        return FileSystemType::ERR_UNKNOWN;
    }

    unsigned char buffer[512];
    ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
    close(fd);

    if (bytes_read != sizeof(buffer)) {
        EL_ERROR("Failed to read device header: {} {}", actualDevicePath_, strerror(errno));
        return FileSystemType::ERR_UNKNOWN;
    }

    // 检查NTFS签名: "NTFS    "
    if (buffer[3] == 'N' && buffer[4] == 'T' && buffer[5] == 'F' && buffer[6] == 'S' && buffer[7] == ' ' &&
        buffer[8] == ' ' && buffer[9] == ' ' && buffer[10] == ' ') {
        EL_INFO("Detected NTFS filesystem by signature: {}", actualDevicePath_);
        return FileSystemType::NTFS;
    }

    // 检查FAT32签名
    if (buffer[82] == 'F' && buffer[83] == 'A' && buffer[84] == 'T' && buffer[85] == '3' && buffer[86] == '2') {
        EL_INFO("Detected FAT32 filesystem by signature: {}", actualDevicePath_);
        return FileSystemType::FAT32;
    }

    // 检查exFAT签名
    if (buffer[3] == 'E' && buffer[4] == 'X' && buffer[5] == 'F' && buffer[6] == 'A' && buffer[7] == 'T') {
        EL_INFO("Detected EXFAT filesystem by signature: {}", actualDevicePath_);
        return FileSystemType::EXFAT;
    }

    EL_WARN("Could not detect filesystem type, defaulting to FAT32: {}", actualDevicePath_);
    return FileSystemType::FAT32;
}

bool StorageDeviceImpl::Repair()
{
    // TODO: 实现修复功能
    return false;
}

FileSystemType StorageDeviceImpl::GetFileSystemType() const
{
    return fileSystemType_;
}

bool StorageDeviceImpl::CheckFileSystem()
{
    // TODO: 实现文件系统检查
    return false;
}

bool StorageDeviceImpl::Defragment()
{
    // TODO: 实现碎片整理
    return false;
}

std::shared_ptr<IStorageDevice> StorageDeviceImpl::CreateStorageDevice(DeviceType type,
                                                                       const std::string &devicePath,
                                                                       const std::string &mountPath)
{
    return std::make_shared<StorageDeviceImpl>(type, devicePath, mountPath);
}

bool StorageDeviceImpl::CreateMountStatusFile()
{
    std::string statusFilePath = mountPoint_ + "/" + MOUNT_STATUS_FILE;
    FILE *fp = fopen(statusFilePath.c_str(), "w");
    if (!fp) {
        EL_ERROR("Failed to create mount status file: {} {}", statusFilePath, strerror(errno));
        return false;
    }
    fclose(fp);
    return true;
}

bool StorageDeviceImpl::RemoveMountStatusFile()
{
    std::string statusFilePath = mountPoint_ + "/" + MOUNT_STATUS_FILE;
    if (unlink(statusFilePath.c_str()) != 0 && errno != ENOENT) {
        EL_ERROR("Failed to remove mount status file: {} {}", statusFilePath, strerror(errno));
        return false;
    }
    return true;
}

bool StorageDeviceImpl::RunFsck()
{
    EL_INFO("Running fsck on device: {}", actualDevicePath_);

    // 根据文件系统类型选择合适的修复工具
    std::string fsckCmd;
    switch (fileSystemType_) {
        case FileSystemType::FAT32:
            fsckCmd = "fsck.vfat -a " + actualDevicePath_;
            break;
        case FileSystemType::EXFAT:
            fsckCmd = "fsck.exfat -a " + actualDevicePath_;
            break;
        case FileSystemType::NTFS:
            fsckCmd = "ntfsfix " + actualDevicePath_;
            break;
        default:
            // 对于未知类型，尝试使用FAT32的修复工具
            EL_WARN("Unknown filesystem type, trying fsck.vfat");
            fsckCmd = "fsck.vfat -a " + actualDevicePath_;
            break;
    }

    std::string output;
    if (!Utils::ExecuteCommand(fsckCmd, &output)) {
        EL_ERROR("fsck failed: {} {}", fsckCmd, output);
        return false;
    }

    EL_INFO("fsck completed successfully: {}", output);
    return true;
}

bool StorageDeviceImpl::CheckAndRepairIfNeeded()
{
    std::string statusFilePath = mountPoint_ + "/" + MOUNT_STATUS_FILE;
    if (Utils::IsFileExists(statusFilePath)) {
        EL_WARN("Found mount status file, device was not unmounted properly: {}", mountPoint_);

        // 先卸载设备
        if (!Unmount()) {
            EL_ERROR("Failed to unmount device for repair: {}", mountPoint_);
            return false;
        }

        // 运行fsck修复
        if (!RunFsck()) {
            EL_ERROR("Failed to repair filesystem: {}", actualDevicePath_);
        }

        // 重新挂载设备
        if (!Mount()) {
            EL_ERROR("Failed to remount device after repair: {}", mountPoint_);
            return false;
        }

        EL_INFO("Device repaired successfully: {}", mountPoint_);
    }
    return true;
}

std::string DeviceStatusToString(DeviceStatus status)
{
    const static std::map<DeviceStatus, std::string> statusToString = {
        {DeviceStatus::ERR_UNKNOWN, "UNKNOWN"},
        {DeviceStatus::ERR_NOT_EXIST, "NOT_EXIST"},
        {DeviceStatus::ERR_DEVICE_ADDED, "DEVICE_ADDED"},
        {DeviceStatus::ERR_DEVICE_REMOVED, "DEVICE_REMOVED"},
        {DeviceStatus::ERR_MOUNTED, "MOUNTED"},
        {DeviceStatus::ERR_UNMOUNTED, "UNMOUNTED"},
        {DeviceStatus::ERR_CAPACITY_WARNING, "CAPACITY_WARNING"},
        {DeviceStatus::ERR_CAPACITY_FULL, "CAPACITY_FULL"},
        {DeviceStatus::ERR_CAPACITY_NORMAL, "CAPACITY_NORMAL"},
        {DeviceStatus::ERR_ERROR, "ERROR"}};

    auto it = statusToString.find(status);
    return it != statusToString.end() ? it->second : "ERR_UNKNOWN";
}

} // namespace Storage
} // namespace El
